package com.xmy.cultivate.controller;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.xmy.cultivate.entity.*;
import com.xmy.cultivate.enums.StatusStaffEnum;
import com.xmy.cultivate.mapper.AdminMapper;
import com.xmy.cultivate.mapper.StaffMapper;
import com.xmy.cultivate.service.*;
import com.xmy.cultivate.util.Code;
import com.xmy.cultivate.util.CommonUtil;
import com.xmy.cultivate.util.Result;
import com.xmy.cultivate.util.ResultCode;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.crypto.hash.Md5Hash;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.context.annotation.Scope;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import java.time.LocalDate;
import java.util.*;

/**
 * <p>
 * 登录账号 前端控制器
 * </p>
 *
 * @author min
 * @since 2022-07-19
 */
@RestController
@RequestMapping("/api/admin")
@Scope("prototype")
@Slf4j
public class AdminController extends BaseController {
    @Autowired
    IAdminService iAdminService;

    @Resource
    AdminMapper adminMapper;

    @Resource
    StaffMapper staffMapper;

    @Autowired
    IRoleService iRoleService;

    @Autowired
    IRoleAdminService iRoleAdminService;

    @Autowired
    IPermissionService iPermissionService;

    @Autowired
    IAppointSchoolService iAppointSchoolService;

    @Autowired
    ICompanyService iCompanyService;

    @Autowired
    ICodeVersionAdminSeeService iCodeVersionAdminSeeService;

    @Lazy
    @Autowired
    ICodeVersionService iCodeVersionService;

    @Autowired
    private ISystemOperationLogService iSystemOperationLogService;

    @Autowired
    private IQuarterService iQuarterService;

    @GetMapping("index")
    public void index() {
        Page<Admin> page = new Page<>(1, 2);
        IPage<Admin> result = adminMapper.selectPage(page, null);
        //System.out.print(result.getRecords());
    }

    @PostMapping(value = "/auth/login")
    public Result login(@RequestBody Map<String, Object> reMap) {
        //构造登录令牌
        try {

            /**
             * 密码加密：
             *     shiro提供的md5加密
             *     Md5Hash:
             *      参数一：加密的内容
             *              111111   --- abcd
             *      参数二：盐（加密的混淆字符串）（用户登录的用户名）
             *              111111+混淆字符串
             *      参数三：加密次数
             *
             */

            //String username,String password

            String username = (String) reMap.get("username");
            String passwordParm = (String) reMap.get("password");

            //System.out.print("username:"+username);
            //System.out.println();
            //System.out.print("password:"+password);
            String password = new Md5Hash(passwordParm, username, 3).toString();
            //System.out.print("password:"+password);

            UsernamePasswordToken upToken = new UsernamePasswordToken(username, password);

            Subject subject = SecurityUtils.getSubject();
            //2.调用subject进行登录
            subject.login(upToken);//获取session

            String sid = (String) subject.getSession().getId();
            Map<String, Object> data = new HashMap<>();
            data.put("token", sid);

            long timeout = SecurityUtils.getSubject().getSession().getTimeout();
            //System.out.println(timeout+"毫秒");

            //1.subject获取所有的安全数据集合
            PrincipalCollection principals = subject.getPrincipals();
            if (principals != null && !principals.isEmpty()) {
                //2.获取安全数据
                Admin admin = (Admin) principals.getPrimaryPrincipal();
                if (admin.getIsLogin().equals(0)) {
                    // 记录登录日志
                    saveOperationLog(admin.getId(), "账号冻结，登录失败");
                    return new Result(Code.ERROR, "", "不能登录，请与管理员联系");
                }
                Staff staffInfo = admin.getStaffInfo();
                if (staffInfo != null && staffInfo.getStatus().equals(StatusStaffEnum.OUT)) {
                    // 记录登录日志
                    saveOperationLog(admin.getId(), "账号冻结，登录失败");
                    return new Result(Code.ERROR, "", "已离职，不能登陆");
                }
                admin.setPwdShow(passwordParm);
                iAdminService.updateById(admin);

                // 记录登录日志
                saveOperationLog(admin.getId(), null);
            }

            Company company = iCompanyService.getById(1L);
            if (company != null) {
                if (company.getIsMaintain() == 1) {
                    if (username.equals("admin")) {
                        return new Result(Code.OK, data);
                    } else {
                        return new Result(Code.ERROR, "", "系统维护中……");
                    }
                } else {
                    return new Result(Code.OK, data);
                }
            } else {
                return new Result(Code.OK, data);
            }

            //return new Result(Code.OK,data);

        } catch (Exception e) {
            //return new Result(Code.ERROR,e.getMessage());
            //return new Result(Code.OK,data);
            return new Result(ResultCode.MOBILEORPASSWORDERROR);
        }
    }

    private void saveOperationLog(Long id, String operationContent) {
        Quarter nowQuarter = iQuarterService.getNowQuarter();
        Integer yearPart = nowQuarter.getYearPart();
        Integer num = nowQuarter.getNum();
        LocalDate nowDate = LocalDate.now();
        LocalDate plusDays = nowDate.plusDays(1L);
        QueryWrapper<SystemOperationLog> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("year_part", yearPart);
        queryWrapper.eq("quarter_num", num);
        queryWrapper.eq("created_id", id);
        queryWrapper.eq("operation_type", 2);
        queryWrapper.between("created_at", nowDate, plusDays);
        long count = iSystemOperationLogService.count(queryWrapper);
        if (count < 1) {
            // 每天每个老师第一次登录时需要记录
            SystemOperationLog systemOperationLog = new SystemOperationLog();
            systemOperationLog.setFunctionName("登录");
            systemOperationLog.setOperationType(2);
            systemOperationLog.setYearPart(yearPart);
            systemOperationLog.setQuarterNum(num);
            systemOperationLog.setOperationContent(operationContent);
            systemOperationLog.setCreatedId(id);
            iSystemOperationLogService.save(systemOperationLog);
        }
    }


    @PostMapping(value = "/densification")
    @ApiOperation("修改密码")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "username", value = "用户名", required = true, dataType = "String"),
            @ApiImplicitParam(name = "password", value = "想修改的密码", required = true, dataType = "String"),
            @ApiImplicitParam(name = "passwordNext", value = "再次输入密码", required = true, dataType = "String"),
            @ApiImplicitParam(name = "passwordOld", value = "原始密码", required = true, dataType = "String")
    })
    public Result Densification(@RequestBody Map<String, Object> reMap) {
        /**
         * 密码加密：
         *     shiro提供的md5加密
         *     Md5Hash:
         *      参数一：加密的内容
         *              111111   --- abcd
         *      参数二：盐（加密的混淆字符串）（用户登录的用户名）
         *              111111+混淆字符串
         *      参数三：加密次数
         *
         */

        //String username,String password
        //String username = (String) reMap.get("username");
        String passwordOld = (String) reMap.get("passwordOld");
        String password = (String) reMap.get("password");
        String passwordNext = (String) reMap.get("passwordNext");
        if (!passwordNext.equals(password)) {
            return new Result(Code.ERROR, null, "两次输入密码不一致！");
        }
        Admin admin = adminMapper.selectById(this.adminId);
        if (Objects.equals(admin, null)) {
            return new Result(Code.ERROR, null, "当前用户不存在,数据异常!");
        }
        passwordOld = new Md5Hash(passwordOld, this.adminModel.getAccount(), 3).toString();
        if (!Objects.equals(passwordOld, admin.getPwd())) {
            return new Result(Code.ERROR, null, "旧密码错误!");
        }
        boolean rs = CommonUtil.isPasswordAvailable("", password);
        if (!rs) {
            return new Result(Code.ERROR, null, "密码不能包含4位以上连续数字或字符");
        }

        String passwordMd5 = new Md5Hash(password, this.adminModel.getAccount(), 3).toString();
        admin.setPwd(passwordMd5);
        admin.setPwdShow(password);
        adminMapper.updateById(admin);
        return new Result(Code.OK, null, "密码修改成功~");
    }


    /**
     * 修改初始密码
     *
     * @param reMap
     * @return
     */
    @PostMapping(value = "/updateInitPwd")
    public Result updateInitPwd(@RequestBody Map<String, Object> reMap) {

        String password = (String) reMap.get("password");
        String confirmPassword = (String) reMap.get("confirmPassword");
        if (!confirmPassword.equals(password)) {
            return new Result(Code.ERROR, null, "两次输入密码不一致！");
        }
        boolean rs = CommonUtil.isPasswordAvailable("", password);
        if (!rs) {
            return new Result(Code.ERROR, null, "密码不能包含4位以上连续数字或字符");
        }

        Admin admin = adminMapper.selectById(this.adminId);
        if (Objects.equals(admin, null)) {
            return new Result(Code.ERROR, null, "当前用户不存在,数据异常!");
        }

        String passwordMd5 = new Md5Hash(password, this.adminModel.getAccount(), 3).toString();
        admin.setPwd(passwordMd5);
        admin.setPwdShow(password);
        adminMapper.updateById(admin);
        return new Result(Code.OK, null, "初始密码修改成功~");
    }


    @PostMapping(value = "/resetting")
    @ApiOperation("重置密码")
    public Result resetting() {
        /**
         * 密码加密：
         *     shiro提供的md5加密
         *     Md5Hash:
         *      参数一：加密的内容
         *              111111   --- abcd
         *      参数二：盐（加密的混淆字符串）（用户登录的用户名）
         *              111111+混淆字符串
         *      参数三：加密次数
         *
         */
        String password = "123456";
        Admin admin = adminMapper.selectById(this.adminId);
        if (Objects.equals(admin, null)) {
            return new Result(Code.ERROR, null, "当前用户不存在,数据异常!");
        }
        String passwordMd5 = new Md5Hash(password, this.adminModel.getAccount(), 3).toString();
        admin.setPwd(passwordMd5);
        admin.setPwdShow(password);
        adminMapper.updateById(admin);
        return new Result(Code.OK, null, "密码重置成功~当前密码为123456");
    }


    @PostMapping(value = "/auth/logout")
    public Result logout(@RequestBody Map<String, Object> reMap) {
        return new Result(Code.OK);
    }


    @GetMapping("/admin/get_info")
    public Result getInfo() {

        Admin admin = this.adminModel;
        Integer isInitPwd = 0;
        String showPwd = iAdminService.getShowPwd(admin.getId());

        boolean rs = CommonUtil.isPasswordAvailable("", showPwd);
        if (!rs) {
            isInitPwd = 1;
        }

        //System.out.print("admin-id");
        //System.out.print(admin.getId());

        QueryWrapper<Staff> staffQueryWrapper = new QueryWrapper<>();
        staffQueryWrapper.eq("admin_id", admin.getId());
        Staff staff = staffMapper.selectOne(staffQueryWrapper);
        String username = "";
        Map<String, Object> data = new HashMap<>();
        if (staff != null) {
            data.put("avatar", staff.getHeadImg());
            username = staff.getName();//真实姓名
        } else {
            data.put("avatar", "");
        }
        if (admin.getIsSuper() == 1) {
            username = "超级管理员";
        }
        if (!admin.getAccount().equals("admin")) {
            admin.setIsSuper(0);
        }

        data.put("isInitPwd", isInitPwd);//真实姓名
        data.put("username", username);//真实姓名

        data.put("admin_id", admin.getId());
        data.put("isSuper", admin.getIsSuper());
        data.put("name", admin.getAccount());

        /**
         * 校区
         */
        List<String> schoolNameList = new ArrayList<>();
        List<String> roleNameList = new ArrayList<>();
        if (admin.getGovernMode() == 1) {
            schoolNameList.add("全部校区");
            //roleNameList.add("全角色");
        } else {
            schoolNameList = iAppointSchoolService.getSchoolNameListForForId(admin.getId(), 2);
        }
        //获取角色
        roleNameList = iRoleAdminService.getAdminRoleNameList(admin.getId());

        data.put("schoolNameList", schoolNameList);
        data.put("roleNameList", roleNameList);


        List<String> roleIdList = new ArrayList<>();
        Set<String> permissionSet = new HashSet<>();
        Set<String> permissionFeatureSet = new HashSet<>();//功能权限

        QueryWrapper<Role> roleQueryWrapper = new QueryWrapper<>();
        if (admin.getIsSuper() != 1 && !admin.getId().equals(1568138350324350975L)) {
            List<Role> roleList = new ArrayList<>();
            roleQueryWrapper.inSql("id", "select role_id from role_admin where admin_id = " + admin.getId());
            roleList = iRoleService.list(roleQueryWrapper);
            if (roleList.size() > 0) {
                for (Role role : roleList) {
                    roleIdList.add(role.getId().toString());
                }
            }
            /*
            String schoolIdListStr = "";
            for (Long id:admin.getSchoolIdList()){
                //schoolIdListStr = String.join(",",Long.toString(id));
                schoolIdListStr += id +",";
            }

            String finalSchoolIdListStr = schoolIdListStr;
            //System.out.print("schoolIdListStr："+schoolIdListStr);
            if(com.baomidou.mybatisplus.core.toolkit.StringUtils.isNotBlank(finalSchoolIdListStr)){
                //去掉可最后一个逗号
                finalSchoolIdListStr = finalSchoolIdListStr.substring(0,finalSchoolIdListStr.length() -1);
                String finalSchoolIdListStr1 = finalSchoolIdListStr;
                roleQueryWrapper.and(i->i.eq("govern_mode",1).or().inSql("id","select for_id from appoint_school where type=5 and school_id in ("+ finalSchoolIdListStr1 +")"));
            }else {
                roleQueryWrapper.and(i->i.eq("govern_mode",1));
            }

            //roleQueryWrapper.//角色适用校区
            List<Role> roleList = new ArrayList<>();
            roleList = iRoleService.list(roleQueryWrapper);
            if(roleList.size()>0){
                for (Role role:roleList){
                    roleIdList.add(role.getId().toString());
                }
                String roleIds =  StringUtils.join(roleIdList,',');
                QueryWrapper<Permission> permissionQueryWrapper = new QueryWrapper<>();
                permissionQueryWrapper.eq("type",1);//菜单
                //permissionQueryWrapper.and(i->i.inSql("id","select permission_id from role_permission where role_id in("+roleIds+")").or().inSql("id","select permission_id from staff_permission where type =1 and staff_id ="+this.adminId+""));
                permissionQueryWrapper.inSql("id","select permission_id from role_permission where role_id in("+roleIds+")");
                List<Permission> permissionList = iPermissionService.list(permissionQueryWrapper);
                for (Permission permission:permissionList){
                    permissionSet.add(permission.getCode());
                }

                permissionQueryWrapper = new QueryWrapper<>();
                permissionQueryWrapper.eq("type",2);//功能
                permissionQueryWrapper.inSql("id","select permission_id from role_permission where role_id in("+roleIds+")");
                List<Permission> permissionFeatureList = iPermissionService.list(permissionQueryWrapper);
                for (Permission permission:permissionFeatureList){
                    permissionFeatureSet.add(permission.getCode());
                }
            }*/
            permissionSet = iPermissionService.getPermissoinCodeForAdmin(this.adminId, 1);//菜单
            permissionFeatureSet = iPermissionService.getPermissoinCodeForAdmin(this.adminId, 2);//功能


        } else {
            roleIdList.add("super");
            permissionSet.add("isSuper");
            /*QueryWrapper<Permission> permissionQueryWrapper = new QueryWrapper<>();
            permissionQueryWrapper.eq("type",1);//菜单
            List<Permission> permissionList = iPermissionService.list(permissionQueryWrapper);
            for (Permission permission:permissionList){
                permissionSet.add(permission.getCode());
            }

            permissionQueryWrapper = new QueryWrapper<>();
            permissionQueryWrapper.eq("type",2);//功能
            List<Permission> permissionFeatureList = iPermissionService.list(permissionQueryWrapper);
            for (Permission permission:permissionFeatureList){
                permissionFeatureSet.add(permission.getCode());
            }*/
        }
        data.put("roles", roleIdList);
        data.put("permissionList", permissionSet);
        data.put("permissionFeatureList", permissionFeatureSet);

        return new Result(Code.OK, data);
    }

    @ApiOperation("查看会员信息里的引导状态")
    @GetMapping("/admin/getSeeGuide")
    public Result getSeeGuide() {
        QueryWrapper<CodeVersionAdminSee> codeVersionAdminSeeQueryWrapper = new QueryWrapper<>();
        codeVersionAdminSeeQueryWrapper.eq("admin_id", this.adminId);
        CodeVersionAdminSee iCodeVersionAdminSeeServiceOne = iCodeVersionAdminSeeService.getOne(codeVersionAdminSeeQueryWrapper);
        CodeVersionAdminSee iCodeVersionAdminSeeServiceNew = new CodeVersionAdminSee();
        if (iCodeVersionAdminSeeServiceOne == null) {
            QueryWrapper<CodeVersion> queryWrapper = new QueryWrapper<>();
            queryWrapper.eq("state", 1);// 0待发布；1已发布；2已撤回
            if (this.adminModel.getIsSuper() == 0) {
                QueryWrapper<RoleAdmin> roleAdminQueryWrapper = new QueryWrapper<>();
                roleAdminQueryWrapper.eq("admin_id", this.adminId);
                List<RoleAdmin> roleAdminList = iRoleAdminService.list(roleAdminQueryWrapper);
                if (!roleAdminList.isEmpty()) {
                    queryWrapper.and(q -> {
                        for (RoleAdmin roleAdmin : roleAdminList) {
                            q.like("terminal_state", roleAdmin.getRoleId()).or();
                        }
                    });
                } else {
                    return new Result(Code.OK, "", "查询版本管理最新发布十条~");
                }
            }
            long count = iCodeVersionService.count(queryWrapper);
            if (count > 0L) {
                iCodeVersionAdminSeeServiceNew.setSeeGuide(0);
                iCodeVersionAdminSeeServiceNew.setSeeVersion(0);
            } else {
                iCodeVersionAdminSeeServiceNew.setSeeGuide(1);
                iCodeVersionAdminSeeServiceNew.setSeeVersion(1);
            }
            iCodeVersionAdminSeeServiceNew.setAdminId(this.adminId);
        } else {
            iCodeVersionAdminSeeServiceNew = iCodeVersionAdminSeeServiceOne;
        }
        return new Result(Code.OK, iCodeVersionAdminSeeServiceNew, "查看会员信息里的引导状态");
    }

    @ApiOperation("更改引导状态为已查看")
    @GetMapping("/admin/editSeeGuide")
    public Result editSeeGuide() {
        QueryWrapper<CodeVersionAdminSee> codeVersionAdminSeeQueryWrapper = new QueryWrapper<>();
        codeVersionAdminSeeQueryWrapper.eq("admin_id", this.adminId);
        long count = iCodeVersionAdminSeeService.count(codeVersionAdminSeeQueryWrapper);
        if (count != 0L) {
            UpdateWrapper<CodeVersionAdminSee> codeVersionAdminSeeUpdateWrapper = new UpdateWrapper<>();
            codeVersionAdminSeeUpdateWrapper.eq("admin_id", this.adminId);
            codeVersionAdminSeeUpdateWrapper.set("see_guide", 1);
            iCodeVersionAdminSeeService.update(codeVersionAdminSeeUpdateWrapper);
        } else {
            CodeVersionAdminSee codeVersionAdminSee = new CodeVersionAdminSee();
            codeVersionAdminSee.setAdminId(this.adminId);
            codeVersionAdminSee.setSeeGuide(1);
            iCodeVersionAdminSeeService.save(codeVersionAdminSee);
        }
        CodeVersionAdminSee iCodeVersionAdminSeeServiceOne = iCodeVersionAdminSeeService.getOne(codeVersionAdminSeeQueryWrapper);
        return new Result(Code.OK, iCodeVersionAdminSeeServiceOne, "更改引导状态为已查看");
    }

    @ApiOperation("更改版本公告状态为已查看")
    @GetMapping("/admin/editSeeVersion")
    public Result editSeeVersion() {
        QueryWrapper<CodeVersionAdminSee> codeVersionAdminSeeQueryWrapper = new QueryWrapper<>();
        codeVersionAdminSeeQueryWrapper.eq("admin_id", this.adminId);
        long count = iCodeVersionAdminSeeService.count(codeVersionAdminSeeQueryWrapper);
        if (count != 0L) {
            UpdateWrapper<CodeVersionAdminSee> codeVersionAdminSeeUpdateWrapper = new UpdateWrapper<>();
            codeVersionAdminSeeUpdateWrapper.eq("admin_id", this.adminId);
            codeVersionAdminSeeUpdateWrapper.set("see_version", 1);
            iCodeVersionAdminSeeService.update(codeVersionAdminSeeUpdateWrapper);
        } else {
            CodeVersionAdminSee codeVersionAdminSee = new CodeVersionAdminSee();
            codeVersionAdminSee.setAdminId(this.adminId);
            codeVersionAdminSee.setSeeVersion(1);
            iCodeVersionAdminSeeService.save(codeVersionAdminSee);
        }
        CodeVersionAdminSee iCodeVersionAdminSeeServiceOne = iCodeVersionAdminSeeService.getOne(codeVersionAdminSeeQueryWrapper);
        return new Result(Code.OK, iCodeVersionAdminSeeServiceOne, "更改自己的版本公告状态为已查看");
    }
}
